using System;
using System.Collections.Generic;

namespace NDomain.Reflection
{
    public class ModuleInfo
    {
        private string name;
        private List<EntityInfo> entities = new List<EntityInfo>();
        private List<ModuleInfo> modules = new List<ModuleInfo>();
        private List<AggregateInfo> aggregates = new List<AggregateInfo>();
        private List<ServiceInfo> services = new List<ServiceInfo>();
        private List<ValueObjectInfo> valueObjects = new List<ValueObjectInfo>();

        public ModuleInfo(string name)
        {
            this.name = name;
        }

        public string Name
        {
            get { return name; }
        }

        public IList<EntityInfo> Entities
        {
            get { return entities.AsReadOnly(); }
        }

        public IList<ModuleInfo> Modules
        {
            get { return modules.AsReadOnly(); }
        }

        public IList<AggregateInfo> Aggregates
        {
            get { return aggregates.AsReadOnly(); }
        }

        public IList<ServiceInfo> Services
        {
            get { return services.AsReadOnly(); }
        }

        public IList<ValueObjectInfo> ValueObjects
        {
            get { return valueObjects.AsReadOnly(); }
        }

        internal void AddEntity(EntityInfo entity)
        {
            entities.Add(entity);
        }

        internal void AddModule(ModuleInfo module)
        {
            modules.Add(module);
        }

        internal AggregateInfo AddAggregate(AggregateInfo aggregate)
        {
            aggregates.Add(aggregate);
            return aggregate;
        }

        internal AggregateInfo GetAggregate(string name)
        {
            AggregateInfo aggregate = aggregates.Find(delegate(AggregateInfo a) { return a.Name == name; });
            if (aggregate == null)
            {
                aggregate = new AggregateInfo(name);
                AddAggregate(aggregate);
            }
            return aggregate;
        }

        public void AddService(ServiceInfo service)
        {
            services.Add(service);
        }

        public void AddValueObject(ValueObjectInfo valueObjectInfo)
        {
            valueObjects.Add(valueObjectInfo);
        }

        public EntityInfo GetEntity(string entityName)
        {
            EntityInfo entity = entities.Find(delegate(EntityInfo e) { return e.Name == entityName; });

            if (entity == null)
                foreach (AggregateInfo aggregate in aggregates)
                    entity = aggregate.GetEntity(entityName);

            if (entity == null)
                throw new InvalidOperationException("Entity not found");

            return entity;
        }
    }
}